Copied from upstream:
https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/221de852fda3

# HG changeset patch
# User Randell Jesup <rjesup@jesup.org>
# Date 1455862087 18000
# Node ID 221de852fda32714a9e484774ceafafb450ea73c
# Parent  b03db72e32f6e3acdc9f8705371cb222d7e6c456
Bug 1240760: Update DataChannel::Close() r=mcmanus, a=ritu

MozReview-Commit-ID: 7nN9h3M3O8w

diff --git a/netwerk/sctp/datachannel/DataChannel.cpp b/netwerk/sctp/datachannel/DataChannel.cpp
--- a/netwerk/sctp/datachannel/DataChannel.cpp
+++ b/netwerk/sctp/datachannel/DataChannel.cpp
@@ -1771,17 +1771,17 @@ DataChannelConnection::HandleStreamReset
           }
           NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
                                     DataChannelOnMessageAvailable::ON_CHANNEL_CLOSED, this,
                                     channel));
           mStreams[channel->mStream] = nullptr;
 
           LOG(("Disconnected DataChannel %p from connection %p",
                (void *) channel.get(), (void *) channel->mConnection.get()));
-          channel->Destroy();
+          channel->DestroyLocked();
           // At this point when we leave here, the object is a zombie held alive only by the DOM object
         } else {
           LOG(("Can't find incoming channel %d",i));
         }
       }
     }
   }
 
@@ -2498,17 +2498,17 @@ DataChannelConnection::CloseInt(DataChan
       mStreams[channel->mStream] = nullptr;
     } else {
       SendOutgoingStreamReset();
     }
   }
   aChannel->mState = CLOSING;
   if (mState == CLOSED) {
     // we're not going to hang around waiting
-    channel->Destroy();
+    channel->DestroyLocked();
   }
   // At this point when we leave here, the object is a zombie held alive only by the DOM object
 }
 
 void DataChannelConnection::CloseAll()
 {
   LOG(("Closing all channels (connection %p)", (void*) this));
   // Don't need to lock here
@@ -2552,23 +2552,25 @@ DataChannel::~DataChannel()
   // wrong, nothing bad happens.  A worst it's a leak.
   NS_ASSERTION(mState == CLOSED || mState == CLOSING, "unexpected state in ~DataChannel");
 }
 
 void
 DataChannel::Close()
 {
   ENSURE_DATACONNECTION;
+  RefPtr<DataChannelConnection> connection(mConnection);
   mConnection->Close(this);
 }
 
 // Used when disconnecting from the DataChannelConnection
 void
-DataChannel::Destroy()
+DataChannel::DestroyLocked()
 {
+  mConnection->mLock.AssertCurrentThreadOwns();
   ENSURE_DATACONNECTION;
 
   LOG(("Destroying Data channel %u", mStream));
   MOZ_ASSERT_IF(mStream != INVALID_STREAM,
                 !mConnection->FindChannelByStream(mStream));
   mStream = INVALID_STREAM;
   mState = CLOSED;
   mConnection = nullptr;
diff --git a/netwerk/sctp/datachannel/DataChannel.h b/netwerk/sctp/datachannel/DataChannel.h
--- a/netwerk/sctp/datachannel/DataChannel.h
+++ b/netwerk/sctp/datachannel/DataChannel.h
@@ -331,19 +331,20 @@ public:
     {
       NS_ASSERTION(mConnection,"NULL connection");
     }
 
 private:
   ~DataChannel();
 
 public:
-  void Destroy(); // when we disconnect from the connection after stream RESET
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataChannel)
 
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataChannel)
+  // when we disconnect from the connection after stream RESET
+  void DestroyLocked();
 
   // Close this DataChannel.  Can be called multiple times.  MUST be called
   // before destroying the DataChannel (state must be CLOSED or CLOSING).
   void Close();
 
   // Set the listener (especially for channels created from the other side)
   void SetListener(DataChannelListener *aListener, nsISupports *aContext);
 

